package top.csmcool.musicapi.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.csmcool.musicapi.domain.UserPlatformBindInfo;
import top.csmcool.musicapi.domain.Users;
import top.csmcool.musicapi.enums.PlatformEnum;
import top.csmcool.musicapi.enums.StatusCode;
import top.csmcool.musicapi.model.api.navidrome.SongCollection;
import top.csmcool.musicapi.model.playlist.*;
import top.csmcool.musicapi.model.result.Request;
import top.csmcool.musicapi.model.result.Result;
import top.csmcool.musicapi.resource.MusicResource;
import top.csmcool.musicapi.service.MusicService;
import top.csmcool.musicapi.service.UserPlatformBindInfoService;
import top.csmcool.musicapi.util.GlobalCache;
import top.csmcool.musicapi.util.ResultUtil;
import top.csmcool.musicapi.util.SpringUtils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Description 音乐实现类
 * @Author shizhe
 * @Date 2025/1/27
 */

@Service
@RequiredArgsConstructor
public class MusicServiceImpl implements MusicService {

    private final UserPlatformBindInfoService userPlatformBindInfoService;
    private final ThreadPoolExecutor threadPoolExecutor;

    @Override
    public Result<List<PlayListMusicInfo>> getTracks(Request<TracksRequest> requestRequest) {
        Result<List<PlayListMusicInfo>> result = checkResult(requestRequest);
        if (result != null) {
            return result;
        }

        // 获取音乐资源并执行搜索
        MusicResource musicResource = getMusicResource(requestRequest);
        return ResultUtil.success(musicResource.getTracks(requestRequest.getBody(), getCurrentUser(), getPlatformBindInfo(requestRequest)));
    }

    @Override
    public Result<List<LyricInfo>> getLyric(Request<LyricRequest> requestRequest) {
        Result<List<LyricInfo>> result = checkResult(requestRequest);
        if (result != null) {
            return result;
        }

        // 获取音乐资源并执行搜索
        MusicResource musicResource = getMusicResource(requestRequest);
        return ResultUtil.success(musicResource.getLyric(requestRequest.getBody(), getCurrentUser(), getPlatformBindInfo(requestRequest)));
    }

    @Override
    public Result<List<SongCollection>> playlist(Request<PlayListRequest> requestRequest) {
        Result<List<SongCollection>> result = checkResult(requestRequest);
        if (result != null) {
            return result;
        }

        // 获取音乐资源并执行搜索
        MusicResource musicResource = getMusicResource(requestRequest);
        List<SongCollection> playList = musicResource.getPlayList(requestRequest.getBody(), getCurrentUser(), getPlatformBindInfo(requestRequest));
        playList.forEach(playListSongCollection -> {
            playListSongCollection.setPlatform(requestRequest.getPlatform());
        });
        return ResultUtil.success(playList);
    }

    @Override
    public Result<List<PlayListMusicInfo>> search(Request<SearchRequest> requestRequest) {
        Result<List<PlayListMusicInfo>> result = checkResult(requestRequest);
        if (result != null) {
            return result;
        }

        List<PlayListMusicInfo> list = new LinkedList<>();

        String[] platforms = requestRequest.getPlatform().split(",");
        List<Future<List<PlayListMusicInfo>>> furures = new ArrayList<>();

        for (String platform : platforms) {
            Callable<List<PlayListMusicInfo>> stringCallable = getListCallable(requestRequest, platform);
            Future<List<PlayListMusicInfo>> future = threadPoolExecutor.submit(stringCallable);
            furures.add(future);
        }

        for (Future<List<PlayListMusicInfo>> furure : furures) {
            try {
                List<PlayListMusicInfo> playListMusicInfos = furure.get(30, TimeUnit.SECONDS);
                list.addAll(playListMusicInfos);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }

        // 获取音乐资源并执行搜索
        return ResultUtil.success(list);
    }

    private Callable<List<PlayListMusicInfo>> getListCallable(Request<SearchRequest> requestRequest, String platform) {
        Object loginId = StpUtil.getLoginId();
        // 批量搜索歌曲
        return () -> {
            List<PlayListMusicInfo> search = new ArrayList<>();
            try {
                MusicResource musicResource = getMusicResource(platform);
                // 模拟任务执行
                search = musicResource.search(requestRequest.getBody(), getCurrentUser(loginId), getPlatformBindInfo(platform, loginId));
                search.forEach(playListMusicInfo -> {
                    playListMusicInfo.setPlatform(platform);
                    String name = PlatformEnum.getPlatformByEnum(platform).getName();
                    playListMusicInfo.setPlatformName(name);
                });
            } catch (Exception e) {
                return search;
            }
            return search;
        };
    }

    @Override
    public Result<List<SongCollection>> personalizedPlaylist(Request<PlayListRequest> requestRequest) {
        Result<List<SongCollection>> result = checkResult(requestRequest);
        if (result != null) {
            return result;
        }

        // 获取音乐资源并获取公共播放列表
        MusicResource musicResource = getMusicResource(requestRequest);
        List<SongCollection> publicPlayList = musicResource.getPublicPlayList(requestRequest.getBody(), getCurrentUser(), getPlatformBindInfo(requestRequest));
        publicPlayList.forEach(playListSongCollection -> {
            playListSongCollection.setPlatform(requestRequest.getPlatform());
        });
        return ResultUtil.success(publicPlayList);
    }

    @Override
    public Result<SongInfo> getSongUrl(Request<SongUrlRequest> requestRequest) {
        Result<SongInfo> result = checkResult(requestRequest);
        if (result != null) {
            return result;
        }

        // 获取音乐资源并获取公共播放列表
        MusicResource musicResource = getMusicResource(requestRequest);
        return ResultUtil.success(musicResource.getSongUrl(requestRequest.getBody(), getCurrentUser(), getPlatformBindInfo(requestRequest)));
    }

    private MusicResource getMusicResource(Request<?> request) {
        return SpringUtils.getBean(request.getPlatform());
    }

    private MusicResource getMusicResource(String platform) {
        return SpringUtils.getBean(platform);
    }

    private Users getCurrentUser() {
        Object loginId = StpUtil.getLoginId();
        return (Users) GlobalCache.get(String.valueOf(loginId));
    }

    private Users getCurrentUser(Object loginId) {
        return (Users) GlobalCache.get(String.valueOf(loginId));
    }

    private UserPlatformBindInfo getPlatformBindInfo(Request<?> request) {
        Object loginId = StpUtil.getLoginId();
        return getUserPlatformBindInfo(loginId, request.getPlatform());
    }

    private UserPlatformBindInfo getPlatformBindInfo(String platform, Object loginId) {
        return getUserPlatformBindInfo(loginId, platform);
    }

    private UserPlatformBindInfo getUserPlatformBindInfo(Object loginId, String platformCode) {
        QueryWrapper<UserPlatformBindInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", loginId);
        queryWrapper.eq("platform_code", platformCode);
        return userPlatformBindInfoService.getOne(queryWrapper);
    }

    public <T>Result<T> checkResult(Request<?> request) {
        boolean isLogin = !StpUtil.isLogin();
        if (isLogin) {
            return ResultUtil.failure(StatusCode.NEED_LOGIN);
        }

        if (request.getPlatform() == null || request.getBody() == null) {
            return ResultUtil.failure(StatusCode.NEED_PARAM);
        }

        try {
            if(!request.getPlatform().contains(",")) {
                SpringUtils.getBean(request.getPlatform());
            }
        } catch (Exception e) {
            return ResultUtil.failure(StatusCode.PLATFORM_ERROR);
        }

        return null;
    }
}
